package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service.WeChatPayService;
import com.ruoyi.system.utils.SignUtils;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Signer;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @ProjectName: back
 * @Package: com.ruoyi.system.service.impl
 * @ClassName: WechatPayServiceImpl
 * @Author: haiyue
 * @Description:
 * @Date: 2025/6/5 上午 9:36:46
 * @Version: 1.0
 */
@Service
public class WechatPayServiceImpl implements WeChatPayService {
    private static final Logger log = LoggerFactory.getLogger(WechatPayServiceImpl.class);

    private final NativePayService nativePayService;

    private final String appId;
    /**商户号*/

    private final String merchantId;
    /**API V3密钥*/

    private final String apiV3Key;

    private final String merchantSerialNumber;

    private final String privateKeyPath;

    private CloseableHttpClient httpClient;

    @Autowired
    public WechatPayServiceImpl(Config config,@Value("${wx.pay.apiV3key}") String apiV3Key,
                                @Value("${wx.pay.privateKeyPath}") String privateKeyPath,
                                @Value("${wx.pay.merchantSerialNumber}") String merchantSerialNumber,
                                @Value("${wx.pay.merchantId}") String merchantId,
                                @Value("${wx.pay.appId}") String appId) throws Exception {
        this.nativePayService = new NativePayService.Builder().config(config).build();
        this.merchantId = merchantId;
        this.apiV3Key = apiV3Key;
        this.privateKeyPath = privateKeyPath;
        this.merchantSerialNumber = merchantSerialNumber;
        this.appId = appId;
        this.httpClient = initClient();
    }

    @Override
    public String createNativePayOrder(String outTradeNo, int totalAmount, String description, String notifyUrl) {
        // 构建支付请求
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(totalAmount);
        request.setAmount(amount);
        request.setAppid(appId);
        request.setMchid(merchantId);
        request.setDescription(description);
        request.setNotifyUrl(notifyUrl);
        request.setOutTradeNo(outTradeNo);

        // 调用API生成支付链接
        PrepayResponse response = nativePayService.prepay(request);
        //返回二维码链接
        return response.getCodeUrl();
    }

    @Override
    public Map<String, String> createAppletPrepayOrder(String outTradeNo, int totalAmount, String description,String notifyUrl,  String openId) throws Exception {
        // 组装请求参数
        JSONObject requestBody = new JSONObject();
        requestBody.put("appid", appId);
        requestBody.put("mchid", merchantId);
        requestBody.put("out_trade_no", outTradeNo);
        // 单位：分
        JSONObject amount = new JSONObject();
        amount.put("total", totalAmount);
        requestBody.put("amount",amount);
        requestBody.put("description", description);
        // 回调地址（需公网可访问）
        requestBody.put("notify_url", notifyUrl);

        // 小程序支付需指定支付方式为JSAPI，并传入OpenID
        JSONObject payer = new JSONObject();
        payer.put("openid", openId);
        requestBody.put("payer", payer);

        // 发送请求到微信支付API
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setEntity(new StringEntity(requestBody.toJSONString(), StandardCharsets.UTF_8));

        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            String result = EntityUtils.toString(response.getEntity());
            JSONObject resultJson = JSONObject.parseObject(result);

            // 解析预支付返回结果（获取prepay_id）
            String prepayId = resultJson.getString("prepay_id");
            if (StringUtils.isEmpty(prepayId)) {
                throw new RuntimeException("预支付订单创建失败：" + result);
            }

            // 生成小程序支付参数（需用商户私钥签名）
            return generateJsapiParams(prepayId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private CloseableHttpClient initClient() throws Exception {

        InputStream inputStream = Files.newInputStream(new File(privateKeyPath).toPath());
        // 加载商户私钥
        PrivateKey privateKey = PemUtil.loadPrivateKey(inputStream);

        // 创建签名器
        Signer signer = new PrivateKeySigner(merchantSerialNumber, privateKey);

        // 创建凭据
        WechatPay2Credentials credentials = new WechatPay2Credentials(merchantId, signer);

        // 初始化证书管理器
        CertificatesManager certManager = CertificatesManager.getInstance();
        certManager.putMerchant(merchantId, credentials, apiV3Key.getBytes());

        // 获取证书验证器
        com.wechat.pay.contrib.apache.httpclient.auth.Verifier verifier = certManager.getVerifier(merchantId);

        // 构建 HttpClient
        return WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNumber, privateKey)
                .withValidator(new WechatPay2Validator(verifier))
                .build();
    }

    @Override
    public AjaxResult selectWxOrderDetail(String transactionId) throws Exception {
        String url = String.format("https://api.mch.weixin.qq.com/v3/pay/transactions/id/%s?mchid=%s",
                transactionId, merchantId);

        HttpGet request = new HttpGet(url);
        request.setHeader("Accept", "application/json");

        try (CloseableHttpResponse response = httpClient.execute(request)) {
            int statusCode = response.getStatusLine().getStatusCode();
            String body = EntityUtils.toString(response.getEntity());

            if (statusCode == 200) {
                return AjaxResult.success(JSONObject.parseObject(body));
            } else {
                log.error("查询失败，状态码: {}, 响应: {}", statusCode, body);
                return AjaxResult.error("查询失败，状态码:{}",statusCode);
            }
        }
    }

    // 生成小程序支付所需参数
    private Map<String, String> generateJsapiParams(String prepayId) throws Exception {
        Map<String, String> params = new HashMap<>();
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        String packageStr = "prepay_id=" + prepayId;
        String signType = "RSA";

        // 生成签名
        String signData = appId + "\n" +
                timeStamp + "\n" +
                nonceStr + "\n" +
                packageStr + "\n";

//        InputStream inputStream = Files.newInputStream(new File(privateKeyPath).toPath());
//        // 加载商户私钥
//        PrivateKey privateKey = PemUtil.loadPrivateKey(inputStream);
//
//        // 创建签名器
//        Signer paySign = new PrivateKeySigner(merchantSerialNumber, privateKey);
        String paySign = SignUtils.sign(signData, privateKeyPath);

        params.put("appId", appId);
        params.put("timeStamp", timeStamp);
        params.put("nonceStr", nonceStr);
        params.put("package", packageStr);
        params.put("signType", signType);
        params.put("paySign", paySign);

        return params;
    }
}
